home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1989, 1990, 1991, 1992, John F. Haugh II
- * All rights reserved.
- *
- * Permission is granted to copy and create derivative works for any
- * non-commercial purpose, provided this copyright notice is preserved
- * in all copies of source code, or included in human readable form
- * and conspicuously displayed on all copies of object code or
- * distribution media.
- */
-
- #include <sys/types.h>
- #include <signal.h>
- #include <stdio.h>
- #include "pwd.h"
- #include <utmp.h>
- #include <fcntl.h>
- #ifdef BSD
- #include <strings.h>
- #define strchr index
- #define strrchr rindex
- #else
- #include <string.h>
- #include <memory.h>
- #endif
- #include "config.h"
-
- #if defined(BSD) || defined(SUN)
- #include <sgtty.h>
- #define USE_SGTTY 1
- #endif
- #if defined(USG) || defined(SUN4)
- #ifdef _POSIX_SOURCE
- #include <termios.h>
- #define USE_TERMIOS 1
- #else
- #include <termio.h>
- #define USE_TERMIO 1
- #endif
- #endif
-
- #ifdef USE_SYSLOG
- #include <syslog.h>
-
- #ifndef LOG_WARN
- #define LOG_WARN LOG_WARNING
- #endif
- #endif
-
- #ifndef lint
- static char sccsid[] = "@(#)sulogin.c 3.10 23:56:58 3/7/92";
- #endif
-
- char name[BUFSIZ];
- char pass[BUFSIZ];
- char home[BUFSIZ];
- char prog[BUFSIZ];
- char mail[BUFSIZ];
-
- struct passwd pwent;
- struct utmp utent;
-
- #ifdef USE_SGTTY
- struct sgttyb termio;
- #endif
- #ifdef USE_TERMIO
- struct termio termio;
- #endif
- #ifdef USE_TERMIOS
- struct termios termio;
- #endif
-
- #ifndef MAXENV
- #define MAXENV 64
- #endif
-
- char *newenvp[MAXENV];
- int newenvc = 0;
- int maxenv = MAXENV;
- extern char **environ;
- extern char *getpass();
-
- extern char *getdef_str();
-
- #ifndef ALARM
- #define ALARM 60
- #endif
-
- #ifndef RETRIES
- #define RETRIES 3
- #endif
-
- catch (sig)
- int sig;
- {
- exit (1);
- }
-
- /*ARGSUSED*/
- int
- main (argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
- {
- char *getenv ();
- char *ttyname ();
- char *getpass ();
- char *tz ();
- char *cp;
-
- #ifdef USE_SGTTY
- ioctl (0, TIOCGETP, &termio);
- termio.sg_flags |= (ECHO|CRMOD);
- termio.sg_flags &= ~(RAW|CBREAK);
- ioctl (0, TIOCSETN, &termio);
- #endif
- #ifdef USE_TERMIO
- ioctl (0, TCSETA, &termio);
- termio.c_iflag |= (ICRNL|IXON);
- termio.c_oflag |= (OPOST|ONLCR);
- termio.c_cflag |= (CREAD);
- termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK);
- ioctl (0, TCSETAF, &termio);
- #endif
- #ifdef USE_TERMIOS
- tcgetattr (0, &termio);
- termio.c_iflag |= (ICRNL|IXON);
- termio.c_oflag |= (CREAD);
- termio.c_lflag |= (ECHO|ECHOE|ECHOK|ICANON|ISIG);
- tcsetattr (0, TCSANOW, &termio);
- #endif
- #ifdef USE_SYSLOG
- openlog ("sulogin", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
- #endif
- if (argc > 1) {
- close (0);
- close (1);
- close (2);
-
- if (open (argv[1], O_RDWR) >= 0) {
- dup (0);
- dup (0);
- } else {
- #ifdef USE_SYSLOG
- syslog (LOG_WARN, "cannot open %s\n", argv[1]);
- #endif
- exit (1);
- }
- }
- if (access (PWDFILE, 0) == -1) { /* must be a password file! */
- printf ("No password file\n");
- #ifdef USE_SYSLOG
- syslog (LOG_WARN, "No password file\n");
- #endif
- exit (1);
- }
- #ifndef DEBUG
- if (getppid () != 1) { /* parent must be INIT */
- #ifdef USE_SYSLOG
- syslog (LOG_WARN, "Pid == %d, not 1\n", getppid ());
- #endif
- exit (1);
- }
- #endif
- if (! isatty (0) || ! isatty (1) || ! isatty (2))
- exit (1); /* must be a terminal */
-
- while (*envp) /* add inherited environment, */
- addenv (*envp++); /* some variables change later */
-
- if (cp = getdef_str("ENV_TZ"))
- addenv (*cp == '/' ? tz(cp) : cp);
- if (cp = getdef_str("ENV_HZ"))
- addenv (cp); /* set the default $HZ, if one */
- (void) strcpy (name, "root"); /* KLUDGE!!! */
-
- signal (SIGALRM, catch); /* exit if the timer expires */
- alarm (ALARM); /* only wait so long ... */
-
- while (1) { /* repeatedly get login/password pairs */
- entry (name, &pwent); /* get entry from password file */
- if (pwent.pw_name == (char *) 0) {
- printf ("No password entry for 'root'\n");
- #ifdef USE_SYSLOG
- syslog (LOG_WARN, "No password entry for 'root'\n");
- #endif
- exit (1);
- }
-
- /*
- * Here we prompt for the root password, or if no password is
- * given we just exit.
- */
-
- /* get a password for root */
- if (! (cp = getpass ("Type control-d for normal startup,\n\
- (or give root password for system maintenance):"))) {
- #ifdef USE_SYSLOG
- syslog (LOG_INFO, "Normal startup\n");
- #endif
- #ifdef TELINIT
- execl ("/etc/telinit", "telinit", RUNLEVEL, (char *) 0);
- #endif
- exit (0);
- } else
- strcpy (pass, cp);
-
- if (valid (pass, &pwent)) /* check encrypted passwords ... */
- break; /* ... encrypted passwords matched */
-
- puts ("Login incorrect");
- #ifdef USE_SYSLOG
- syslog (LOG_WARN, "Incorrect root password\n");
- #endif
- }
- alarm (0);
- signal (SIGALRM, SIG_DFL);
- environ = newenvp; /* make new environment active */
-
- puts ("Entering System Maintenance Mode");
- #ifdef USE_SYSLOG
- syslog (LOG_INFO, "System Maintenance Mode\n");
- #endif
-
- /*
- * Normally there would be a utmp entry for login to mung on
- * to get the tty name, date, etc. from. We don't need all that
- * stuff because we won't update the utmp or wtmp files. BUT!,
- * we do need the tty name so we can set the permissions and
- * ownership.
- */
-
- if (cp = ttyname (0)) { /* found entry in /dev/ */
- if (strrchr (cp, '/') != (char *) 0)
- strcpy (utent.ut_line, strrchr (cp, '/') + 1);
- else
- strcpy (utent.ut_line, cp);
- }
- if (getenv ("IFS")) /* don't export user IFS ... */
- addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
-
- setup (&pwent); /* set UID, GID, HOME, etc ... */
-
- shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
- /*NOTREACHED*/
- }
-